#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
__all__ = []

from .. import formlib as layout
from .. import helpstrings as hs
from .. import hint
from .. import pilelib as stack
from ..gamelib import info as gi, state, game
from ..packlib import place, info as cs
from ..forms import napoleon as NapoleonLayout
from ..piles import (napoleon as NapoleonStack, casket as CasketStack,
                     foundation as FoundationStack, freecell as FreeCellStack,
                     talon as TalonStack,)
from ..utillib.misc import kwdefault

Wrap = stack.StackWrapper
GT, SL = gi.GT, gi.SL


class Braid(game.Game):
    """
    Finish 2 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.napolean.BraidSmallLayout
        - row [4 over 2 cols E, 4 over 2 cols  W braid, no offset]
        - reserve [1 N 1 S row E W braid, no offset]
        - braid [1 N, braid offset]
        - talon [1 E foundation, no offset]
        - waste [1 E talon, no offset]
        - foundation [8 over 2 col E, no offset]
      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=3)
        Deal 1 card per waste on click. 2 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack
        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.Foundation
        Init base card. Build in rank by same suit wrap from base card. Dir
        determined by 2nd card on any pile. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.RowStack
        Init 1 card. Build any from any but reserve or braid. Play top. Max 1
       card.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.Reserve
        Init 1 card. Build any. Play top. Gap deal 1 card from braid. Max 1
        card.

      _braid_ : pysollib.stack.Stack
        .. pysollib.stack.OpenStack (max_cards=20)
        Init deal 20 open card. Build none. Play top.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.DefaultHint
    """
    __info__ = dict(id=0x3345c, name='Braid', game_type=(GT.NAPOLEON |
                    GT.POPULAR | GT.ATARI | GT.GNOME), decks=2, redeals=2,
                    version='1.03', skill_level=SL.BALANCED, altnames=(
                    'Der Zopf', 'Plait', 'Pigtail'))
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _layout_ = NapoleonLayout.BraidSmallLayout
    _talon_ = Wrap(stack.WasteTalon, max_rounds=3)
    _waste_ = stack.WasteStack
    _foundation_ = NapoleonStack.Foundation
    _row_ = NapoleonStack.RowStack
    _braid_ = Wrap(stack.OpenStack, max_cards=20)
    _reserve_ = NapoleonStack.Reserve

    def _create_game(self, **kw):
        """
        _create_game([rows=4, playcards=14]) -> Layout

        Add a canvas info label for base_rank next to talon.

        :returns: current layout with piles and their texts set.

        :seealso: `pysollib.layouts.napoleon` for keyword definitions.
        """
        kwdefault(kw, rows=8, reserves=4, braidcards=20)
        l, s = super(Braid, self)._create_game(**kw), self.s
        s['braid'].append(self._braid_(l.s['braid'][0].x, l.s['braid'][0].y, game=self,
                                    offset=l.s['braid'][0].offset))
        l.defaultStackGroups()
        return l

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return any one 1 rank not trump on top for _foundation_ deal.
        """
        ncards = self.s['braid'][0].cap['max_cards']
        n = m = -1 - ncards - len(self.s['rows'])
        while cards[n].suit >= len(self['suits']):
            n -= 1
        cards[n], cards[m] = cards[m], cards[n]
        return cards

    def _start(self, **kw):
        """
        _start([]) -> None

        Deal max_cards per braid. Deal 1 card per reserve and row. Deal base
        card per 1 foundation. Deal 1 card per waste. Set foundation base
        rank for each.
        """
        for i in range(self.s['braid'][0].cap['max_cards']):
            self.s['talon'].dealRow(rows=self.s['braid'], frames=0)
        self.s['talon'].dealRow(rows=self.s['rows'] + self.s['reserves'],
                                     frames=4)
        base_rank = self.s['talon'].TOPCARD['rank']
        self.s['talon'].dealBaseCards(ncards=1, saveinfo=False)
        self._save_stack_caps(self.s['foundations'], base_rank=base_rank)

    @property
    def _highlight_piles(self):
        """
        Get stacks to highlight for possible move.

        :return: empty.
        :rtype: tuple
        """
        return ()

    @state.move_state('fill')
    def _auto_fill(self, stack):
        """
        While inner braid has cards, fill empty reserve with 1 of its card.
        """
        s = self.s
        if not stack.cards and stack in s['reserves'] and s['braid'][0].cards:
            self.move(1, s['braid'][0], stack)

    @state.not_state('is_preview')
    def _update_text(self):
        """
        _update_text(self) -> None

        Update canvas info label with chosen build direction for foundation.
        """
        if not self.texts['info']:
            return
        cap = self.s['foundations'][0].cap
        base_rank = cap['base_rank']
        text = ('' if base_rank == cs.ANY
                   else '{0} {1}'.format(self.RANKS[base_rank],
                                         hs.BUILD_DIR(cap['dir'])))
        self.texts['info'].config(text=text)


class LongBraid(Braid):
    """
    Finish 2 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.napolean.BraidSmallLayout
        - row [4 over 2 cols E, 4 over 2 cols  W braid, no offset]
        - reserve [1 N 1 S row E W braid, no offset]
        - braid [1 N, braid offset]
        - talon [1 E foundation, no offset]
        - waste [1 E talon, no offset]
        - foundation [8 over 2 col E, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=3)
        Deal 1 card per waste on click. 2 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack
        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.Foundation
        Init base card. Build in rank by same suit wrap from base card. Dir
        determined by 2nd card on any pile. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.RowStack
        Init 1 card. Build any from any but reserve or braid. Play top. Max 1
       card.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.Reserve
        Init 1 card. Build any. Play top. Gap deal 1 card from braid. Max 1
        card.

      _braid_ : pysollib.stack.Stack
        .. pysollib.stack.OpenStack (max_cards=24)
        Init deal 24 open card. Build none. Play top.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.DefaultHint
    """
    __info__ = dict(id=0x334ff, name='Long Braid', game_type=GT.NAPOLEON,
                    decks=2, redeals=2, skill_level=SL.BALANCED, altnames=(
                    'Der lange Zopf',), version='4.20')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _braid_ = Wrap(stack.OpenStack, max_cards=24)

    def _create_game(self, **kw):
        """
        _create_game([braidcards=24]) -> Layout

        Add a canvas info label for base_rank next to talon.

        :returns: current layout with piles and their texts set.

        :seealso: `pysollib.layouts.napoleon` for keyword definitions.
        """
        kw.setdefault('braidcards', 24)
        return super(LongBraid, self)._create_game(**kw)


class BigBraid(Braid):
    """
    Finish 3 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.napolean.BraidSmallLayout
        - row [4 over 2 cols E, 4 over 2 cols  W braid, no offset]
        - reserve [1 N 1 S row E W braid, no offset]
        - braid [1 N, braid offset]
        - talon [1 E foundation, no offset]
        - waste [1 E talon, no offset]
        - foundation [12 over 3 col E, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=3)
        Deal 1 card per waste on click. 2 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack
        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.Foundation
        Init base card. Build in rank by same suit wrap from base card. Dir
        determined by 2nd card on any pile. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.RowStack
        Init 1 card. Build any from any but reserve or braid. Play top. Max 1
       card.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.Reserve
        Init 1 card. Build any. Play top. Gap deal 1 card from braid. Max 1
        card.

      _braid_ : pysollib.stack.Stack
        .. pysollib.stack.OpenStack (max_cards=20)
        Init deal 20 open card. Build none. Play top.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.DefaultHint
    """
    __info__ = dict(id=0x3364e, name='Big Braid', game_type=(GT.NAPOLEON |
                    GT.ORIGINAL), decks=3, redeals=2, skill_level=SL.BALANCED,
                    version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70


class Fort(Braid):
    """
    Finish 2 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.napolean.BraidSmallLayout
        - row [4 over 2 cols E, 4 over 2 cols  W braid, no offset]
        - reserve [1 N 1 S row E W braid, no offset]
        - braid [1 N, braid offset]
        - talon [1 E foundation, no offset]
        - waste [1 E talon, no offset]
        - foundation [8 over 2 col E, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=3)
        Deal 1 card per waste on click. 2 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack
        Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.foundation.AceKingSS_Foundation
        Init deal base ACE KING. Build in rank by same suit. W up; E down.
        Play top. Base ace E, king W.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.RowStack
        Init 1 card. Build any from any but reserve or braid. Play top. Max 1
       card.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.Reserve
        Init 1 card. Build any. Play top. Gap deal 1 card from braid. Max 1
        card.

      _braid_ : pysollib.stack.Stack
        .. pysollib.stack.OpenStack (max_cards=21)
        Init deal 21 open card. Build none. Play top.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.DefaultHint
    """
    __info__ = dict(id=0x335b6, name='Fort', game_type=GT.NAPOLEON, decks=2,
                    redeals=2, skill_level=SL.BALANCED, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _foundation_ = FoundationStack.AceKingSS_Foundation
    _braid_ = Wrap(stack.OpenStack, max_cards=21)

    def _create_game(self, **kw):
        """
        _create_game([braidcards=21]) -> Layout

        Add a canvas info label for base_rank next to talon.

        :returns: current layout with piles and their texts set.

        :seealso: `pysollib.layouts.napoleon` for keyword definitions.
        """
        kw.setdefault('braidcards', 21)
        return super(Fort, self)._create_game(**kw)

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return ACE and KING of suit on top by rank, suit, deck for
        _foundation_ deal.
        """
        return place.MoveToTop(cards, place.OneAceKing)

    def _start(self, **kw):
        """
        _start([]) -> None

        Deal ace per E and king per W foundation. Deal max_cards per braid.
        Deal 1 card per reserve and row. Deal 1 card per waste.
        """
        self.s['talon'].dealRow(rows=self.s['foundations'], frames=0)
        for i in range(self.s['braid'][0].cap['max_cards']):
            self.s['talon'].dealRow(rows=self.s['braid'], frames=0)
        self.s['talon'].dealRow()
        self.s['talon'].dealRow(self.s['reserves'])


class Backbone(game.Game):
    """
    Finish 2 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.napolean.BackboneLayout
        - row [4 E, 4 W S foundation, vert offset]
        - reserve [2 N. vert offset. 1 offset S, no offset]
        - talon [1 S foundation, no offset]
        - waste [1 E talon, no offset]
        - foundation [4 NE, 4 NW, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=3)
        Deal 1 card per waste on click. 2 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack
        Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation
        Build up in rank by same suit. Play top. Base ace.

      _row_ : pysollib.stack.Stack
        .. pysollib.stack.SS_RowStack (max_move=1)
        Init 1 card. Build down in rank by same suit. Play top.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.BackboneStack (maxcards=11) * 2,
          pysollib.stack.OpenStack
        Init 11 card per N, 1 card per S. Build none. Play top S 1st.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x335c8, name='Backbone', game_type=GT.NAPOLEON,
                    decks=2, redeals=0, skill_level=SL.BALANCED,
                    version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = NapoleonLayout.BackboneLayout
    _talon_ = Wrap(stack.WasteTalon, max_rounds=3)
    _waste_ = stack.WasteStack
    _foundations_ = stack.SS_Foundation
    _rows_ = Wrap(stack.SS_RowStack, max_move=1)
    _reserve_ = (Wrap(NapoleonStack.BackboneStack, maxcards=11),
                stack.OpenStack,)
    _hint_ = hint.CautiousDefaultHint

    def _create_game(self, **kw):
        """
        _create_game([rows=8, playcards=10, holdcards=11]) -> Layout

        :returns: current layout with piles and their texts set.

        :seealso: `pysollib.layouts.napoleon` for keyword definitions.
        """
        l, s = self._layout_(self), self.s
        kwdefault(kw, rows=8, playcards=10, holdcards=11)
        l.create(**kw)
        self.table_size = l.size
        s['foundations'] = [self._foundation_(p.x, p.y, game=self,
                                suit=p['suit']) for p in l.s['foundations']]
        s['reserves'] = [self._reserve_[0](p.x, p.y, game=self,
                             offset=p.offset) for p in l.s['reserves'][:2]]
        s['reserves'] = [self._reserve_[1](l.s['reserve'][-1].x,
                                           l.s['reserve'][-1].y, game=self)]
        s['rows'] = [self._row_(p.x, p.y, game=self) for p in l.s['rows']]
        s['talon'] = self._talon_(l.s['talon'].x, l.s['talon'].y, game=self)
        s['wastes'] = [self._waste_(p.x, p.y, game=self) for p in l.s['wastes']]
        l.defaultAll()
        return l

    def _start(self, **kw):
        """
        _start([]) -> None

        Deal 11 card per N, 1 card per S reserve. Deal 1 card per row. Deal 1
        card per waste.
        """
        for i in range(self.s['reserves'][0].cap['max_cards'] - 1):
            self.s['talon'].deal_row(rows=self.s['reserves'][:2], frames=0)
        self.s['talon'].deal_row(rows=self.s['reserves'], frames=0)
        self.s['talon'].deal_row()


class BackbonePlus(Backbone):
    """
    Finish 2 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.napolean.BackboneLayout
        - row [5 E, 5 W S foundation, vert offset]
        - reserve [2 N. vert offset. 1 offset S, no offset]
        - talon [1 S foundation, no offset]
        - waste [1 E talon, no offset]
        - foundation [4 NE, 4 NW, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=3)
        Deal 1 card per waste on click. 2 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack
        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation
        Build up in rank by same suit. Play top. Base ace.

      _row_ : pysollib.stack.Stack
        .. pysollib.stack.SS_RowStack (max_move=1)
        Init 1 card. Build down in rank by same suit. Play top.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stacks.napoleon.BackboneStack (maxcards=11) * 2,
          pysollib.stack.OpenStack
        Init 11 card per N, 1 card per S. Build none. Play top S 1st.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x335c9, name='Backbone +', game_type=GT.NAPOLEON,
                    decks=2, redeals=0, skill_level=SL.BALANCED,
                    version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _create_game(self, **kw):
        """
        _create_game([rows=8, playcards=10, holdcards=11]) -> Layout

        :returns: current layout with piles and their texts set.

        :seealso: `pysollib.layouts.napoleon` for keyword definitions.
        """
        kw.setdefault('rows', 10)
        return super(Backbone, self)._create_game(**kw)


class Casket(game.Game):
    """
    Finish 2 deck on foundation.

    Layout
        - row [8 around W S E inner reserve, no offset]
        - reserve [5 horz N 1 inner, no offset]
        - talon [1 NW, no offset]
        - waste [1 E, no offset]
        - x-wastes [3 S talon, no offset]
        - foundation [8 over 2 col E, no offset]

    :CVariables:
      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon
        Deal 1 card per waste on click. No redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack (max_cards=1)
        Init 1 card. Build none. Play top. Max 1 card.

      _xwaste_ : pysollib.stack.Stack
        .. pysollib.stacks.freecell.FromWasteReserve (max_cards=MAX)
        Init deal 1 card. Build any card. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation
        Build up in rank by same suit. Play top. Base ace.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.casket.Casket_RowStack (max_move=1)
        Init 1 card per. Build down in rank by same suit from any but reserve.
        Play top.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stack.BasicRowStack,
          pysollib.stacks.freecell.NoFlipReserve
        Init 1 card per N 13 close cards per inner. Build none. Play top. Gap
        deal 1 card from inner to N.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.stacks.casket.Casket_Hint
    """
    __info__ = dict(id=0x33706, name='Casket', game_type=GT.TWO_DECK, decks=2,
                    redeals=0, skill_level=SL.BALANCED, version='1.00fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _wastes_ = (Wrap(FreeCellStack.FromWasteReserve, max_cards=cs.MAX),
                Wrap(stack.WasteStack, max_cards=1),)
    _foundation_ = stack.SS_Foundation
    _row_ = Wrap(CasketStack.Casket_RowStack, max_move=1)
    _reserves_ = (stack.BasicRowStack, FreeCellStack.NoFlipReserve,)
    _hint_ = CasketStack.Casket_Hint

    def _create_game(self, **kw):
        """
        _create_game([]) -> Layout

        :returns: current layout with piles and their texts set.

        :todo: needs seperate layout.
        """
        l, s = layout.Layout(self), self.s
        self.table_size = (l.XM + 10 * l.XS, l.YM + 9 * l.HYS,)
        ddx, ddy = l.XM + 5 * l.HXS, l.YM
        for dx, dy in ((0, 2), (1, 1), (2, 0), (3, 1), (4, 2),):
            x, y = l.delta_coords(x=ddx, y=ddy, dx=dx, dy=dy, fy=4)
            s['reserves'].append(self._reserves_[0](x, y, game=self))
        ddx += l.HXS
        ddy += 3 * l.HYS
        for dx, dy in ((0, 0), (3, 0), (0, 1), (3, 1), (0, 2), (1, 2), (2, 2),
                       (3, 2),):
            x, y = l.delta_coords(x=ddx, y=ddy, dx=dx, dy=dy)
            s['rows'].append(self._row_(x, y, game=self, offset=(0, 0)))
        ddx += 3 * l.HXS
        ddy += l.HYS
        s['reserves'].append(self._reserves_[1](ddx, ddy, game=self))
        l.set_ncards_text(s['reserves'][-1], 's')
        x = l.XM
        for y in l.col_iter(ddy, 3):
            s['wastes'].append(self._wastes_[0](x, y, game=self))
            l.set_ncards_text(s['wastes'][-1], 'ne')
        x += 8 * l.XS
        y = l.YM
        for (x_, y_), suit in zip(self.row_block_iter(x, y, npiles=l.NSUITS,
                                                     nrows=l.NSUIT), l.SUITS):
            self.s['foundations'].append(self._foundation_(x_, y_, game=self,
                                                        suit=suit))
        x, y = l.XM, l.YM
        s['talon'] = self._talon_(x, y, game=self)
        l.set_ncards_text(s['talon'], 's')
        x += l.XS
        s['wastes'].append(self._wastes_[1](x, y, game=self))
        l.defaultGroups()
        self.sg['dropstacks'] += s['xwastes']
        return l

    def _start(self, **kw):
        """
        _start([]) -> None

        Deal 13 close card per inner reserve, Deal 1 card per N reserve and
        rows. Any top card that build on foundation will finish without
        replace. Deal 1 card per waste.
        """
        for i in range(13):
            self.s['talon'].dealRow(rows=self.s['reserves'][-1:], frames=0,
                                 flip=False)
        self.s['talon'].deal_row_or_drop(stacks=self.s['reserves'][:-1])
        self.s['talon'].deal_row_or_drop(stacks=self.s['rows'])
        self.talon_deal(sound=False)

    @state.move_state('fill')
    def _auto_fill(self, stack):
        """
        While inner reserve has cards, fill empty N reserve with 1 of its
        card.
        """
        if (not stack.cards and stack in self.s['reserves'][:-1] and
            self.s['reserve'][-1].cards):
            self.fill(self.s['reserve'][-1], stack)


class Well(game.Game):
    """
    Finish 2 deck on foundation.

    Layout
        - row [4 outer cross arms, 1 S talon, no offset]
        - reserve [4 inner cross arms, no offset]
        - talon [1 NW, no offset]
        - waste [5 E, no offset]
        - foundation [4 corner cross, no offset]

    :CVariables:
      _talon_ : pysollib.stack.Stack
        .. pysollib.stacks.talon.DealWastesRedealLessTalon
        Deal 1 card per waste on click. Decrease deal 1 pile each round. 4
        redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack (max_cards=1)
        Init 1 card. Build none. Play top. Max 1 card.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation (base_rank=KING, mod=13, max_cards=26,
          dir=-1, max_move=0)
        Build down in rank by same suit wrap. Play none. Base king. Max 26
        card.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.casket.Well_RowStack,
          pysollib.stacks.casket.Well_RowStack (base_rank=ACE)
        Init 1 card per. Build cross up in rank by same suit. Play top. Base
        ace S talon. Fill cross with card from neighbor reserve.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stack.OpenStack
        Init 10 card per. Build none. Play top.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x3371d, name='Well', game_type=GT.TWO_DECK, decks=2,
                    redeals=4, skill_level=SL.BALANCED, version='1.00fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = Wrap(TalonStack.DealWastesRedealLessTalon, max_rounds=5)
    _waste_ = stack.WasteStack
    _foundation_ = Wrap(stack.SS_Foundation, base_rank=cs.KING, mod=13,
                        max_cards=26, dir=-1, max_move=0)
    _rows_ = (CasketStack.Well_RowStack,
              Wrap(CasketStack.Well_RowStack, base_rank=cs.ACE),)
    _reserve_ = stack.OpenStack
    _hint_ = hint.CautiousDefaultHint

    def _create_game(self):
        """
        _create_game([]) -> Layout

        :returns: current layout with piles and their texts set.

        :todo: needs seperate layout.
        """
        l, s = layout.Layout(self), self.s
        self.table_size = (l.XM + 6 * l.XS, l.YM + 6 * l.YS + l.TEXT_HEIGHT,)
        suit = 0
        ddx, ddy = l.XM + 3 * l.HXS, l.YM + 3 * l.HYS + l.TEXT_HEIGHT
        for (dx, dy), suit in zip(((3, 0), (0, 3), (3, 3), (0, 0),), l.SUIT):
            x, y = l.delta_coords(x=ddx, y=ddy, dx=dx, dy=dy)
            s['foundations'].append(self._foundation_(x, y, game=self,
                                                   suit=suit))
        ddx -= l.HXS
        ddy -= l.HYS
        for xx, yy in ((0, 2), (2, 0), (4, 2), (2, 4),):
            x, y = l.delta_coords(x=ddx, y=ddy, dx=dx, dy=dy)
            s['rows'].append(self._rows_[0](x, y, game=self, offset=(0, 0)))
        ddx -= l.XS
        s['rows'].append(self._rows_[1](ddx, ddy, game=self, offset=(0, 0)))
        ddx += 2 * l.XS
        ddy += l.YS
        for dx, dy, anchor in ((0, 1, 'e'), (1, 0, 's'), (2, 1, 'w'),
                               (1, 2, 'n')):
            x, y = l.delta_coords(x=ddx, y=ddy, dx=dx, dy=dy)
            s['reserves'].append(self._reserve_(x, y, game=self))
            l.set_ncards_text(s['reserves'][-1], anchor)
        x, y = l.XM, l.YM
        s['talon'] = self._talon_(x, y, game=self)
        l.set_ncards_text(s['talon'], 's')
        for x in l.coliter(x + l.XS, 5):
            s['xwastes'].append(self._waste_(x, y, game=self))
            l.set_ncards_text(s['xwastes'][-1], 's', text_format='%D')
        self.sg['Talons'] = [s['talon']] + s['xwastes']
        self.sg['openstacks'] = s['foundations'] + s['rows']
        self.sg['dropstacks'] = s['rows'] + s['xwastes'] + s['reserves']
        return l

    def _start(self, **kw):
        """
        _start([]) -> None

        Deal 10 card per reserve Deal 1 card per cross row. Deal 1 card per
        waste.
        """
        for i in range(10):
            self.s['talon'].dealRow(rows=self.s['reserves'], frames=0)
        self.s['talon'].dealRow(rows=self.s['rows'][:4])

    @state.move_state('fill')
    def _auto_fill(self, stack):
        """
        While neighbor reserve has cards, fill neighbor row with 1 of its
        card.
        """
        if not stack.cards and stack in self.s['rows'][:4]:
            reserve = self.s['reserves'][self.s['rows'].index(stack)]
            if reserve.cards:
                self.move(1, reserve, stack)

PROVIDES = [Braid, LongBraid, Fort, Backbone, BackbonePlus, BigBraid, Casket,
            Well]